Make lib name optional
authordinesh <dsdiscoverdinesh@gmail.com>
Sun, 21 Jun 2015 10:34:42 +0000 (16:04 +0530)
committerdinesh <dsdiscoverdinesh@gmail.com>
Thu, 2 Jul 2015 17:00:54 +0000 (22:30 +0530)
src/cargo/util/toml.rs
tests/test_cargo_test.rs

index 2bb1a1ff1f7175a8ded593eaec3a256f96271e11..3a94879753ceca1b136f228058ba1e520f5cb7a0 100644 (file)
@@ -302,7 +302,7 @@ struct Context<'a, 'b> {
 fn inferred_lib_target(name: &str, layout: &Layout) -> Option<TomlTarget> {
     layout.lib.as_ref().map(|lib| {
         TomlTarget {
-            name: name.to_string(),
+            name: Some(name.to_string()),
             path: Some(PathValue::Path(lib.clone())),
             .. TomlTarget::new()
         }
@@ -320,7 +320,7 @@ fn inferred_bin_targets(name: &str, layout: &Layout) -> Vec<TomlTarget> {
 
         name.map(|name| {
             TomlTarget {
-                name: name,
+                name: Some(name),
                 path: Some(PathValue::Path(bin.clone())),
                 .. TomlTarget::new()
             }
@@ -332,7 +332,7 @@ fn inferred_example_targets(layout: &Layout) -> Vec<TomlTarget> {
     layout.examples.iter().filter_map(|ex| {
         ex.file_stem().and_then(|s| s.to_str()).map(|name| {
             TomlTarget {
-                name: name.to_string(),
+                name: Some(name.to_string()),
                 path: Some(PathValue::Path(ex.clone())),
                 .. TomlTarget::new()
             }
@@ -344,7 +344,7 @@ fn inferred_test_targets(layout: &Layout) -> Vec<TomlTarget> {
     layout.tests.iter().filter_map(|ex| {
         ex.file_stem().and_then(|s| s.to_str()).map(|name| {
             TomlTarget {
-                name: name.to_string(),
+                name: Some(name.to_string()),
                 path: Some(PathValue::Path(ex.clone())),
                 .. TomlTarget::new()
             }
@@ -356,7 +356,7 @@ fn inferred_bench_targets(layout: &Layout) -> Vec<TomlTarget> {
     layout.benches.iter().filter_map(|ex| {
         ex.file_stem().and_then(|s| s.to_str()).map(|name| {
             TomlTarget {
-                name: name.to_string(),
+                name: Some(name.to_string()),
                 path: Some(PathValue::Path(ex.clone())),
                 .. TomlTarget::new()
             }
@@ -389,11 +389,22 @@ impl TomlManifest {
         let lib = match self.lib {
             Some(ref lib) => {
                 try!(validate_library_name(lib));
-                Some(if layout.lib.is_some() && lib.path.is_none() {
+                Some(if layout.lib.is_some() && lib.name.is_none() && lib.path.is_none() {
                     TomlTarget {
+                        name: Some(project.name.clone()),
                         path: layout.lib.as_ref().map(|p| PathValue::Path(p.clone())),
                         .. lib.clone()
                     }
+                } else if layout.lib.is_some() && lib.path.is_none() {
+                    TomlTarget {
+                        path: layout.lib.as_ref().map(|p| PathValue::Path(p.clone())),
+                        .. lib.clone()
+                    }
+                } else if layout.lib.is_some() && lib.name.is_none() {
+                    TomlTarget {
+                        name: Some(project.name.clone()),
+                        .. lib.clone()
+                    }
                 } else {
                     lib.clone()
                 })
@@ -426,28 +437,46 @@ impl TomlManifest {
         let blacklist = vec!["build", "deps", "examples", "native"];
 
         for bin in bins.iter() {
-            if blacklist.iter().find(|&x| *x == bin.name) != None {
+            if blacklist.iter().find(|&x| *x == bin.name.as_ref().unwrap()) != None {
                 return Err(human(&format!("the binary target name `{}` is \
-                                           forbidden", bin.name)));
+                                           forbidden", bin.name.as_ref().unwrap())));
             }
         }
 
         let examples = match self.example {
-            Some(ref examples) => examples.clone(),
-            None => inferred_example_targets(layout),
+            Some(ref examples) => {
+                for target in examples {
+                    try!(validate_example_name(target));
+                }
+                examples.clone()
+            }
+            None => inferred_example_targets(layout)
         };
 
         let tests = match self.test {
-            Some(ref tests) => tests.clone(),
-            None => inferred_test_targets(layout),
+            Some(ref tests) => {
+                for target in tests {
+                    try!(validate_test_name(target));
+                }
+                tests.clone()
+            }
+            None => inferred_test_targets(layout)
         };
 
-        let benches = if self.bench.is_none() || self.bench.as_ref().unwrap().is_empty() {
-            inferred_bench_targets(layout)
-        } else {
-            self.bench.as_ref().unwrap().iter().map(|t| {
-                t.clone()
-            }).collect()
+        let benches = match self.bench {
+            Some(ref benches) => {
+                for target in benches {
+                    try!(validate_bench_name(target));
+                }
+                if benches.is_empty() {
+                    inferred_bench_targets(layout)
+                } else {
+                    benches.iter().map(|t| {
+                        t.clone()
+                    }).collect()
+                }
+            }
+            None => inferred_bench_targets(layout)
         };
 
         // processing the custom build script
@@ -543,21 +572,52 @@ impl TomlManifest {
 }
 
 fn validate_library_name(target: &TomlTarget) -> CargoResult<()> {
-    if target.name.trim().is_empty() {
-        Err(human(format!("library target names cannot be empty.")))
-    } else if target.name.contains("-") {
-        Err(human(format!("library target names cannot contain hyphens: {}",
-                          target.name)))
-    } else {
-        Ok(())
+    match target.name {
+        Some(ref name) => {
+            if name.trim().is_empty() {
+                Err(human(format!("library target names cannot be empty.")))
+            } else if name.contains("-") {
+                Err(human(format!("library target names cannot contain hyphens: {}",
+                                  name)))
+            } else {
+                Ok(())
+            }
+        },
+        None => Ok(())
     }
 }
 
 fn validate_binary_name(target: &TomlTarget) -> CargoResult<()> {
-    if target.name.trim().is_empty() {
-        Err(human(format!("binary target names cannot be empty.")))
-    } else {
-        Ok(())
+    match target.name {
+        Some(ref name) => {
+            if name.trim().is_empty() {
+                Err(human(format!("binary target names cannot be empty.")))
+            } else {
+                Ok(())
+            }
+        },
+        None => Err(human(format!("binary target bin.name is required")))
+    }
+}
+
+fn validate_example_name(target: &TomlTarget) -> CargoResult<()> {
+    match target.name {
+        Some(_) => Ok(()),
+        None => Err(human(format!("example target example.name is required")))
+    }
+}
+
+fn validate_test_name(target: &TomlTarget) -> CargoResult<()> {
+    match target.name {
+        Some(_) => Ok(()),
+        None => Err(human(format!("test target test.name is required")))
+    }
+}
+
+fn validate_bench_name(target: &TomlTarget) -> CargoResult<()> {
+    match target.name {
+        Some(_) => Ok(()),
+        None => Err(human(format!("bench target bench.name is required")))
     }
 }
 
@@ -615,7 +675,7 @@ fn process_dependencies<F>(cx: &mut Context,
 
 #[derive(RustcDecodable, Debug, Clone)]
 struct TomlTarget {
-    name: String,
+    name: Option<String>,
     crate_type: Option<Vec<String>>,
     path: Option<PathValue>,
     test: Option<bool>,
@@ -643,7 +703,7 @@ struct TomlPlatform {
 impl TomlTarget {
     fn new() -> TomlTarget {
         TomlTarget {
-            name: String::new(),
+            name: None,
             crate_type: None,
             path: None,
             test: None,
@@ -694,7 +754,7 @@ fn normalize(lib: &Option<TomlLibTarget>,
     fn lib_target(dst: &mut Vec<Target>, l: &TomlLibTarget,
                   metadata: &Metadata) {
         let path = l.path.clone().unwrap_or_else(|| {
-            PathValue::Path(Path::new("src").join(&format!("{}.rs", l.name)))
+            PathValue::Path(Path::new("src").join(&format!("{}.rs", l.name.as_ref().unwrap())))
         });
         let crate_types = l.crate_type.clone().and_then(|kinds| {
             kinds.iter().map(|s| LibKind::from_str(s))
@@ -703,7 +763,7 @@ fn normalize(lib: &Option<TomlLibTarget>,
             vec![if l.plugin == Some(true) {LibKind::Dylib} else {LibKind::Lib}]
         });
 
-        let mut target = Target::lib_target(&l.name, crate_types.clone(),
+        let mut target = Target::lib_target(&l.name.as_ref().unwrap(), crate_types.clone(),
                                             &path.to_path(),
                                             metadata.clone());
         configure(l, &mut target);
@@ -716,7 +776,7 @@ fn normalize(lib: &Option<TomlLibTarget>,
             let path = bin.path.clone().unwrap_or_else(|| {
                 PathValue::Path(default(bin))
             });
-            let mut target = Target::bin_target(&bin.name, &path.to_path(),
+            let mut target = Target::bin_target(&bin.name.as_ref().unwrap(), &path.to_path(),
                                                 None);
             configure(bin, &mut target);
             dst.push(target);
@@ -738,7 +798,7 @@ fn normalize(lib: &Option<TomlLibTarget>,
                 PathValue::Path(default(ex))
             });
 
-            let mut target = Target::example_target(&ex.name, &path.to_path());
+            let mut target = Target::example_target(&ex.name.as_ref().unwrap(), &path.to_path());
             configure(ex, &mut target);
             dst.push(target);
         }
@@ -754,9 +814,9 @@ fn normalize(lib: &Option<TomlLibTarget>,
 
             // make sure this metadata is different from any same-named libs.
             let mut metadata = metadata.clone();
-            metadata.mix(&format!("test-{}", test.name));
+            metadata.mix(&format!("test-{}", test.name.as_ref().unwrap()));
 
-            let mut target = Target::test_target(&test.name, &path.to_path(),
+            let mut target = Target::test_target(&test.name.as_ref().unwrap(), &path.to_path(),
                                                  metadata);
             configure(test, &mut target);
             dst.push(target);
@@ -773,9 +833,9 @@ fn normalize(lib: &Option<TomlLibTarget>,
 
             // make sure this metadata is different from any same-named libs.
             let mut metadata = metadata.clone();
-            metadata.mix(&format!("bench-{}", bench.name));
+            metadata.mix(&format!("bench-{}", bench.name.as_ref().unwrap()));
 
-            let mut target = Target::bench_target(&bench.name,
+            let mut target = Target::bench_target(&bench.name.as_ref().unwrap(),
                                                   &path.to_path(),
                                                   metadata);
             configure(bench, &mut target);
@@ -789,11 +849,11 @@ fn normalize(lib: &Option<TomlLibTarget>,
         lib_target(&mut ret, lib, metadata);
         bin_targets(&mut ret, bins,
                     &mut |bin| Path::new("src").join("bin")
-                                   .join(&format!("{}.rs", bin.name)));
+                                   .join(&format!("{}.rs", bin.name.as_ref().unwrap())));
     } else if bins.len() > 0 {
         bin_targets(&mut ret, bins,
                     &mut |bin| Path::new("src")
-                                    .join(&format!("{}.rs", bin.name)));
+                                    .join(&format!("{}.rs", bin.name.as_ref().unwrap())));
     }
 
     if let Some(custom_build) = custom_build {
@@ -802,21 +862,21 @@ fn normalize(lib: &Option<TomlLibTarget>,
 
     example_targets(&mut ret, examples,
                     &mut |ex| Path::new("examples")
-                                   .join(&format!("{}.rs", ex.name)));
+                                   .join(&format!("{}.rs", ex.name.as_ref().unwrap())));
 
     test_targets(&mut ret, tests, metadata, &mut |test| {
-        if test.name == "test" {
+        if test.name.as_ref().unwrap() == "test" {
             Path::new("src").join("test.rs")
         } else {
-            Path::new("tests").join(&format!("{}.rs", test.name))
+            Path::new("tests").join(&format!("{}.rs", test.name.as_ref().unwrap()))
         }
     });
 
     bench_targets(&mut ret, benches, metadata, &mut |bench| {
-        if bench.name == "bench" {
+        if bench.name.as_ref().unwrap() == "bench" {
             Path::new("src").join("bench.rs")
         } else {
-            Path::new("benches").join(&format!("{}.rs", bench.name))
+            Path::new("benches").join(&format!("{}.rs", bench.name.as_ref().unwrap()))
         }
     });
 
index 91304272a3c8dfd01e187cc806e379b2687b28d6..3e34f7c9c19e7a6addfde28dce1c934106e93738 100644 (file)
@@ -683,6 +683,44 @@ test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
                        dir = p.url())));
 });
 
+test!(lib_without_name {
+    let p = project("foo")
+        .file("Cargo.toml", r#"
+            [package]
+            name = "syntax"
+            version = "0.0.1"
+            authors = []
+
+            [lib]
+            test = false
+            doctest = false
+        "#)
+        .file("src/lib.rs", "
+            pub fn foo() {}
+        ")
+        .file("src/main.rs", "
+            extern crate syntax;
+
+            fn main() {}
+
+            #[test]
+            fn test() { syntax::foo() }
+        ");
+
+    assert_that(p.cargo_process("test"),
+                execs().with_status(0)
+                       .with_stdout(&format!("\
+{compiling} syntax v0.0.1 ({dir})
+{running} target[..]syntax-[..]
+
+running 1 test
+test test ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
+
+", compiling = COMPILING, running = RUNNING, dir = p.url())));
+});
+
 test!(bin_there_for_integration {
     let p = project("foo")
         .file("Cargo.toml", r#"